package org.jeecg.module.flow.meter.tcpserver.utils;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.nio.charset.StandardCharsets;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * @Author: 86176
 * @Date: 2024-05-17 9:18
 * @Version: 1.0
 */
@Slf4j
public class FlowMeterUtils {


    /**
     * 根据指定方向将不足length个字节的16进制字符串补0
     *
     * @param str 输入的16进制字符串
     * @param length 目标长度（字节）
     * @return 补0后的16进制字符串
     */
    public static String padWithLeadingZeros(String str,int length) {
        // 检查输入字符串是否为16进制
        if (!str.matches("[0-9a-fA-F]+")) {
            throw new IllegalArgumentException("Invalid hexadecimal string");
        }

        // 获取字节数组
        byte[] bytes = new BigInteger(str, 16).toByteArray();

        // 计算需要补0的字节数
        int bytesLength = bytes.length;
        int zerosToPad = length - bytesLength;
        if (zerosToPad < 0) {
            throw new IllegalArgumentException("Input is too long, should be at most 16 characters");
        }

        // 从高位补0
        byte[] paddedBytes = new byte[length];
        System.arraycopy(bytes, 0, paddedBytes, zerosToPad, bytesLength);

        // 将字节数组转换为16进制字符串
        return String.format("%0" + (length << 1) + "X", new BigInteger(1, paddedBytes));
    }


    /**
     * @description 高低位转化
     * @author 86176
     * @date 2024-05-20 17:52
    */
    public static String stringHeightLowConvert(String s) {
        StringBuilder str = new StringBuilder();
        if (s == null)
            return null;
        if ("".equals(s.trim()))
            return "";
        if (s.length() % 2 == 0) {
            for (int i = s.length() / 2; i > 0; i--) {
                str.append(s, i * 2 - 2, i * 2);
            }
        }
        return str.toString();
    }

    public static String padWithTrailingZeros(String str, int byteLength) {
        // 检查输入字符串是否为16进制
        if (!str.matches("[0-9a-fA-F]+")) {
            throw new IllegalArgumentException("Invalid hexadecimal string");
        }

        if(str.length() < byteLength*2){
            StringBuilder strBuilder = new StringBuilder(str);
            while (strBuilder.length()<byteLength*2){
                strBuilder.append("0");
            }
            str = strBuilder.toString();
        }
        return str;
    }

    public static String parseMeterNumber(String payload){
       String code = stringHeightLowConvert(payload);
       return removeLeadingZeros(code);
    }

    public static String getCurrentTimeFormatted() {
        // 定义日期时间格式
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");

        // 获取当前时间
        LocalDateTime now = LocalDateTime.now();

        // 格式化当前时间
        String formattedTime = now.format(formatter);

        return stringHeightLowConvert(formattedTime);
    }
    public static String hexStringToIPv4(String hexIP) throws UnknownHostException {
        if (hexIP.length() % 2 != 0) {
            throw new IllegalArgumentException("Invalid hex IP, length must be even");
        }

        byte[] ipAddressBytes = new BigInteger(hexIP, 16).toByteArray();

        // IPv4 addresses are 4 bytes, so remove any leading zeros
        while (ipAddressBytes.length > 4 && ipAddressBytes[0] == 0) {
            ipAddressBytes = Arrays.copyOfRange(ipAddressBytes, 1, ipAddressBytes.length);
        }

        return InetAddress.getByAddress(ipAddressBytes).getHostAddress();
    }

    /**
     * 解析不超过5个字节的16进制ASCII表示的端口号字符串为端口号。
     *
     * @param hexPortStr 16进制ASCII表示的端口号字符串。
     * @return 端口号的字符串表示。
     * @throws IllegalArgumentException 如果输入字符串无效或超出长度限制。
     */
    public static int parseHexPortToPortString(String hexPortStr) {
        // 将16进制字符串转换为字节数组
        byte[] bytes = new byte[(hexPortStr.length() + 1) / 2];
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) ((Character.digit(hexPortStr.charAt(2 * i), 16) << 4)
                    + Character.digit(hexPortStr.charAt(2 * i + 1), 16));
        }

        // 假设端口号位于字节数组的最后5个字节（这取决于具体的协议）
        int portLength = Math.min(bytes.length, 5);
        byte[] portBytes = Arrays.copyOfRange(bytes, bytes.length - portLength, bytes.length);

        // 将字节转换为ASCII字符串
        StringBuilder sb = new StringBuilder();
        for (byte b : portBytes) {
            sb.append((char) b);
        }

        int port = Integer.parseInt(sb.toString());
        // 检查端口号的有效性
        if (port < 0 || port > 65535) {
            throw new IllegalArgumentException("The parsed port number is out of valid range (0-65535).");
        }

        return port;
    }

    public static BigDecimal parseSnr(String snr) {
        String snrValue = snr.substring(0, 2);
        String snrSign = snr.substring(2);
        snrValue = isNegative(snrSign)?"-"+snrValue:snrValue;

        // 根据长度确定是否需要除以100
        return snrSign.length() == 4 ? new BigDecimal(snrValue).divide(new BigDecimal(10),1,RoundingMode.HALF_UP): new BigDecimal(snrValue);
    }

    //去掉字符串前面的0
    public static String removeLeadingZeros(String str) {
        if (str.startsWith("0") && !"0".equals(str)) {
            str = str.replaceFirst("^0+", "");
        }
        return str;
    }

    //去掉字符串末尾的0
    public static String trimTrailingZeros(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }

        while (str.endsWith("0") && !"0".equals(str)) {
            str = str.substring(0, str.length() - 1);
        }
        return str;
    }

    public static Integer parseRsrp(String rsrp){
        if(rsrp.length() % 2 != 0){
            return null;
        }
        String newRespStr = stringHeightLowConvert(rsrp);
        String rsrpValue = newRespStr.substring(2);
        return isNegative(newRespStr.substring(0,2))? new BigDecimal(rsrpValue).divide(new BigDecimal(-10),0,RoundingMode.HALF_UP).intValue():new BigDecimal(rsrpValue).divide(BigDecimal.TEN,1,RoundingMode.HALF_UP).intValue();
    }

    public static Integer parseRsrq(String rsrq){
        if(rsrq.length() % 2 != 0){
            return null;
        }
        String newRespStr = stringHeightLowConvert(rsrq);
        String rsrpValue = newRespStr.substring(2);
        return isNegative(newRespStr.substring(0,2))?Integer.parseInt(rsrpValue)*-1:Integer.parseInt(rsrpValue);
    }

    /**脉冲当量解析*/
    public static int parsePulseEquivalent(String payload){
        String newPe = stringHeightLowConvert(payload);
        return new BigInteger(newPe, 16).intValue();
    }
    public static Date parseUploadTime(String payload){
        String newDateStr = String.valueOf(getYear()).substring(0,2)+stringHeightLowConvert(payload);
        return str2Date(newDateStr,new SimpleDateFormat("yyyyMMddHHmmss"));
    }

    public static boolean isNegative(String payload){
        byte[] bytes = new BigInteger(payload, 16).toByteArray();
        return (bytes[0] & 0xFF) == 1;
    }

    //实时累计用量单位kw.h
    public static BigDecimal parseElectricityUsageTotal(String payload){
        String newElectricityUsage = stringHeightLowConvert(payload);
        return isNegative(newElectricityUsage.substring(0,2)) ? new BigDecimal(Integer.parseInt(newElectricityUsage.substring(2),16)).divide(new BigDecimal(-100),2,RoundingMode.HALF_UP): new BigDecimal(Integer.parseInt(newElectricityUsage.substring(2),16)).divide(new BigDecimal(100),2,RoundingMode.HALF_UP);
    }

    //用于电压，电流，有功，无功解析，单相表报文各占用两个字节
    public static BigDecimal parseElectricityVoltage (String payload){
        String str = stringHeightLowConvert(payload);
        BigDecimal bigDecimal = new BigDecimal(new BigInteger(str,16));
        return bigDecimal.divide(BigDecimal.TEN,1, RoundingMode.UP);
    }

    public static Integer parseElectricityWork (String payload){
        String str = stringHeightLowConvert(payload);
        return new BigInteger(str,16).intValue();
    }

    //功率因数
    public static BigDecimal parsePowerFactorAndCurrent(String payload){
        String str = stringHeightLowConvert(payload);
        BigDecimal bigDecimal = new BigDecimal(new BigInteger(str,16));
        return bigDecimal.divide(new BigDecimal(100),2, RoundingMode.UP);
    }

    public static int dataLength(String payload){
        System.out.println(stringHeightLowConvert(payload));
        return Integer.parseInt(stringHeightLowConvert(payload),16);
    }

    public static int getYear() {
        GregorianCalendar calendar = new GregorianCalendar();
        calendar.setTime(new Date());
        return calendar.get(Calendar.YEAR);
    }

    public static Date str2Date(String str, SimpleDateFormat sdf) {
        if (null == str || "".equals(str)) {
            return null;
        }
        Date date = null;
        try {
            date = sdf.parse(str);
            return date;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**特殊计算方式每位-33，高低为转化后得到结果*/
    public static String subtractHexFromHexString(String hexStr) {
        // 确保输入字符串长度是偶数，以便成对处理
        if (hexStr.length() % 2 != 0) {
            throw new IllegalArgumentException("Input hex string length must be even.");
        }

        StringBuilder resultBuilder = new StringBuilder();

        for (int i = 0; i < hexStr.length(); i += 2) {
            // 提取两个字符作为单个字节的十六进制表示
            String byteStr = hexStr.substring(i, i + 2);
            int byteValue = Integer.parseInt(byteStr, 16); // 转换为十进制

            // 执行减法运算
            byteValue -= 0x33;

            // 确保结果在0-255之间，处理可能的负值溢出
            if (byteValue < 0) {
                byteValue += 256; // 对于负值，进行模256运算以回到有效范围内
            }

            // 将结果转换回两位的十六进制字符串，并添加到结果中
            resultBuilder.append(String.format("%02X", byteValue));
        }

        // 返回结果，此时已经是高位在前、低位在后的格式
        return stringHeightLowConvert(resultBuilder.toString());
    }

    public static String addHexFromHexString(String hexStr) {
        // 确保输入字符串长度是偶数，以便成对处理
        if (hexStr.length() % 2 != 0) {
            throw new IllegalArgumentException("Input hex string length must be even.");
        }

        StringBuilder resultBuilder = new StringBuilder();

        for (int i = 0; i < hexStr.length(); i += 2) {
            // 提取两个字符作为单个字节的十六进制表示
            String byteStr = hexStr.substring(i, i + 2);
            int byteValue = Integer.parseInt(byteStr, 16); // 转换为十进制

            // 执行减法运算
            byteValue += 0x33;

            // 确保结果在0-255之间，处理可能的负值溢出
            if (byteValue < 0) {
                byteValue += 256; // 对于负值，进行模256运算以回到有效范围内
            }

            // 将结果转换回两位的十六进制字符串，并添加到结果中
            resultBuilder.append(String.format("%02X", byteValue));
        }

        // 返回结果，此时已经是高位在前、低位在后的格式
        return stringHeightLowConvert(resultBuilder.toString());
    }

    //当天当月累计用量都是按照脉冲当量来计算的 脉冲为1就乘以0.0001，报文是时分秒3字节，累计用量4给字节（需要进行高低位转化）

    public static int parseStatus(String payload){
        if(payload.equals("01")){
            return 1; //断开或者故障
        }else{
            return 0;
        }
    }

    public static String getChecksum(String hexSequence) {
        int sum = 0;
        for (int i = 0; i < hexSequence.length(); i += 2) {
            // 检查是否有足够的字符来形成一个字节
            if (i + 1 < hexSequence.length()) {
                int byteValue = Integer.parseInt(hexSequence.substring(i, i + 2), 16);
                sum += byteValue;
            }
        }
        return toHexString(sum & 0xFF); // 取模256并保留低8位
    }

    public static String toHexString(int num){
        return String.format("%02X", num);
    }

    public static String toHexString(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X ", b)); // 每个字节转换为16进制并添加空格
        }
        return sb.toString().trim(); // 移除末尾的空格并返回字符串
    }

    public static String toHexStringNoSpaces(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02X", b)); // 每个字节转换为16进制并添加空格
        }
        return sb.toString(); // 移除末尾的空格并返回字符串
    }

    public static String byteToUnsignedHexString(byte b) {
        return String.format("%02X", (b & 0xFF));
    }

    public static Date getDateThreadSafe() {
        // 获取当前时间的Instant对象，它是线程安全的
        Instant nowInstant = Instant.now();
        // 将Instant对象转换为Date类型，考虑到时区
        ZoneId systemZoneId = ZoneId.systemDefault();
        return Date.from(nowInstant.atZone(systemZoneId).toInstant());
    }


    public static String getKey(ChannelHandlerContext ctx,Map<String, ChannelHandlerContext> map) {
        String key = "";
        for (Map.Entry<String, ChannelHandlerContext> m : map.entrySet()) {
            if (m.getValue() == ctx) {
                key = (String) m.getKey();
                break;
            }
        }
        return key;
    }

    public static int isBitInt(int value, int position) {
        return ((value >> position) & 1) == 1 ? 1 : 0;
    }

    public static byte[] toBytes(String str){
        if(str == null || str.trim().equals("")){
            return new byte[0];
        }
        byte[] bytes = new byte[str.length() / 2];
        for (int i = 0; i < str.length() /2; i++){
            bytes[i] =  (byte)Integer.parseInt(str.substring(i * 2, i * 2 + 2), 16);
        }
        return bytes;
    }

    public static int[] readIntArrayFromBuffer(ByteBuf buffer) {
        int[] intArray = new int[buffer.readableBytes() / 4];
        for (int i = 0; i < intArray.length; i++) {
            intArray[i] = buffer.readInt();
        }
        return intArray;
    }

    public static String hexToASCIIAlt(String hex) {
        byte[] bytes = new byte[hex.length() / 2];
        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = (byte) Integer.parseInt(hex.substring(i * 2, i * 2 + 2), 16);
        }
        return new String(bytes, StandardCharsets.US_ASCII);
    }

    public static boolean isAboveCreateTimeTwoDay(Date createTime){
        // 使用 Calendar 类将日期加上两天
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(createTime);
        calendar.add(Calendar.DAY_OF_YEAR, 2);
        Date twoDaysLater = calendar.getTime();

        //去掉开户时分秒相关的影响，第二次抄表的时候异常的数据记录下来

        // 获取当前日期并将时间部分设置为相同值
        Calendar currentCalendar = Calendar.getInstance();
        currentCalendar.setTime(new Date());
        currentCalendar.set(Calendar.HOUR_OF_DAY, 0);
        currentCalendar.set(Calendar.MINUTE, 0);
        currentCalendar.set(Calendar.SECOND, 0);
        currentCalendar.set(Calendar.MILLISECOND, 0);
        Date currentDate = currentCalendar.getTime();

        // 将两个日期的时间部分设置为相同值
        Calendar twoDaysLaterCalendar = Calendar.getInstance();
        twoDaysLaterCalendar.setTime(twoDaysLater);
        twoDaysLaterCalendar.set(Calendar.HOUR_OF_DAY, 0);
        twoDaysLaterCalendar.set(Calendar.MINUTE, 0);
        twoDaysLaterCalendar.set(Calendar.SECOND, 0);
        twoDaysLaterCalendar.set(Calendar.MILLISECOND, 0);
        Date twoDaysLaterDate = twoDaysLaterCalendar.getTime();


        // 比较两个日期的大小
        //7-6 7-8 7-10
        //7-9 7-11 7-10
        if (twoDaysLaterDate.after(currentDate)) {
            return false;
        } else if (twoDaysLater.before(currentDate)) {
            return true;
        } else {
            return true;
        }
    }

    public static void main(String[] args) {
        String s = "9097002B768306002B768306002B000000000000000000350000000002210000000000173704211021200006FFAA001000528986112122001419992808666930504917570104FFFFFF007683060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000";
        System.out.println(s.substring(88, 92));
        System.out.println(s.substring(100,120));
        System.out.println(s.substring(121,136));
        int status = Integer.parseInt(s.substring(86,88),16);
        int voltageStatus = isBitInt(status,0); //0:正常 1：报警
        int kongGuanStatus = isBitInt(status,1);
        int reverseStatus = isBitInt(status,2);
        int excessStatus = isBitInt(status,3);
        int waterTemperatureStatus = isBitInt(status,4);
        int eeStatus = isBitInt(status,5);
        int paStatus = isBitInt(status,7);
        System.out.println("电压报警:"+voltageStatus+" 空管报警:"+kongGuanStatus+" 反流报警:"+reverseStatus);
        System.out.println("超量报警:"+excessStatus+" 水温报警:"+waterTemperatureStatus);
        System.out.println("ee报警:"+eeStatus+" 压强报警:"+paStatus);
        System.out.println(s.substring(156).length()/4);
        System.out.println(s.substring(156));
        System.out.println(stringHeightLowConvert("02104022340000"));
        System.out.println(BigDecimal.valueOf(Integer.parseInt(FlowMeterUtils.stringHeightLowConvert("100200"))).divide(new BigDecimal(100),2,RoundingMode.HALF_UP).scaleByPowerOfTen(1));
    }
}
